// Copyright (c) Microsoft Corporation. All rights reserved.
// Licensed under the MIT license.

#ifndef CONFIG_CMD_TASK_H_
#define CONFIG_CMD_TASK_H_

#include <stdint.h>
#include "FreeRTOS.h"
#include "task.h"
#include "semphr.h"
#include "cmd_interface/cerberus_protocol.h"
#include "system/system.h"


struct config_cmd_task_handler;

/**
 * The task context for commands.
 */
struct config_cmd_task {
	struct system *system;									/**< The system manager. */
	uint8_t running;										/**< Flag indicating if an update is running. */
	TaskHandle_t task;										/**< The task that will run the update. */
	SemaphoreHandle_t lock;									/**< Synchronization for task status. */
	uint8_t buffer[CERBERUS_PROTOCOL_MAX_PAYLOAD_PER_MSG];	/**< Buffer of request data. */
	size_t buffer_len;										/**< Amount of data in the buffer. */
	size_t prepare_size;									/**< Size of flash region to prepare. */
	struct config_cmd_task_handler **handlers;				/**< List of registered command handlers. */
	size_t num_handlers;									/**< Number of registered handlers. */
};

/**
 * Defines the functions to support the handling of requests from registered command handlers.
 * Registered command handlers should implement these routines.
 */
struct config_cmd_task_handler {
	/**
	 * Binds a command handler to the task handler instance.
	 *
	 * @param handler The command task handler.
	 * @param task The command task instance.
	 * @param handler_id The registered identifier of the command handler.
	 */
	void (*bind) (struct config_cmd_task_handler *handler, struct config_cmd_task *task,
		uint8_t handler_id);

	/**
	 * Executes the specified command action.
	 *
	 * @param handler The command task handler.
	 * @param action The action to execute.
	 * @param reset Output indicating whether the device needs to be reset or not as a result of the
	 * operation.  This will always be false at the time of execution and only needs to be updated
	 * if a reset is required.
	 */
	void (*execute) (struct config_cmd_task_handler *handler, uint32_t action, bool *reset);
};

int config_cmd_task_init (struct config_cmd_task *task, struct system *system,
	struct config_cmd_task_handler **handler, size_t num_handlers);
int config_cmd_task_start (struct config_cmd_task *task, uint16_t stack_words);

int config_cmd_task_notify (struct config_cmd_task *task, uint8_t handler_id, uint32_t action);


#define	CONFIG_CMD_TASK_ERROR(code)		ROT_ERROR (ROT_MODULE_CONFIG_CMD_TASK, code)

/**
 * Error codes that can be generated by a command configuration task context.
 */
enum {
	CONFIG_CMD_TASK_INVALID_ARGUMENT = CONFIG_CMD_TASK_ERROR (0),	/**< Input parameter is null or not valid. */
	CONFIG_CMD_TASK_NO_MEMORY = CONFIG_CMD_TASK_ERROR (1),			/**< Memory allocation failed. */
};


#endif /* CONFIG_CMD_TASK_H_ */
